/**
 * Misc utils for elRTE
 *
 * @param Object rte - editor
 * @todo Подумать, что из этого реально нужно и навести порядок. Возможно часть перенести в ellib
 *
 * @author:    Dmitry Levashov (dio) dio@std42.ru
 * Copyright: Studio 42, http://www.std42.ru
 */

;(function($){

  $.widget("el.utils", {
    options: {url: null, baseURL: "", path: ""},
  // TODO: add parse rel path ../../etc
    absoluteURL: function(url)
                 {
                   if(!this.options.url)
                     this._url();
                   if (!(url = $.trim(url)))
                     return "";
                 // ссылки на якоря не переводим в абс
                   if (url[0] == "#")
                     return url;
                   var u = $.el.utils.parseURL(url);
                   if (!(u.host || u.path || u.anchor))
                     return "";
                   if (!this.element[0].options.absoluteURLs)
                     return url;
                   if (u.protocol)
                     return url;
                   if (u.host && ((0 <= u.host.indexOf(".")) || (u.host == "localhost")))
                     return [this.options.url.protocol, url].join("://");
                   if (url[0] == "/")
                     url = [this.options.baseURL, url].join("");
                   else
                   {
                     if (!url.indexOf("./") == 0)
                      url = url.substring(2);
                     url = [this.options.baseURL, url].join(this.options.path);
                   }
                   return url;
                 },
    _url: function()
          {
            this.options.url = $.el.utils.parseURL(document.location.href);
            this.options.baseURL = [this.options.url.protocol, "://"].join("");
            if (this.options.url.userInfo)
              this.options.baseURL = [this.options.baseURL, "@"].join(parts.userInfo);
            this.options.baseURL = [this.options.baseURL, this.options.url.host].join("");
            if (this.options.url.port)
              this.options.baseURL = [this.options.baseURL, this.options.url.port].join(":");
            this.options.path = this.options.url.file ? this.options.url.path.substring(0, this.options.url.path.length - this.options.url.file.length) : this.options.url.path;
          },
  // Parse style string into object
    parseStyle: function(s)
                {
                  var st = {};
                  if ((typeof s  == "string") && s.length)
                  {
                    var a = this.element[0].options.allowBrowsersSpecStyles;
                    $.each(s.replace(/&quot;/gi, "'").split(";"), function()
                    {
                      var t = this.toString().split(":");
                      if (t[0] && t[1])
                      {
                        var n = $.trim(t[0]).toLowerCase();
                        var v = $.trim(t[1]);
                        if ((n == "color") || (n == "background-color"))
                          v = v.toLowerCase();
                        if (n && v && (a || (n.substring(0, 1) != "-")))
                          st[n] = v;
                      }
                    });
                  }
                  return st;
                }
  });

  $.el.utils = {
  // media info
    media: [
      {
        type    : "application/x-shockwave-flash",
        classid : ["clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"],
        codebase: "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
      },
      {
        type    : "application/x-director",
        classid : ["clsid:166b1bca-3f9c-11cf-8075-444553540000"],
        codebase: "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"
      },
      {
        type    : "application/x-mplayer2",
        classid : ["clsid:6bf52a52-394a-11d3-b153-00c04f79faa6", "clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95", "clsid:05589fa1-c356-11ce-bf01-00aa0055595a"],
        codebase: "http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"
      },
      {
        type    : "video/quicktime",
        classid : ["clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b"],
        codebase: "http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"
      },
      {
        type    : "audio/x-pn-realaudio-plugin",
        classid : ["clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa"],
        codebase: "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
      }
    ],
  // web safe colors
    colors: {
      aqua   : "#00ffff",
      black  : "#000000",
      blue   : "#0000ff",
      fuchsia: "#ff00ff",
      gray   : "#808080",
      green  : "#008000",
      lime   : "#00ff00",
      maroon : "#800000",
      navy   : "#000080",
      olive  : "#808000",
      orange : "#ffa500",
      purple : "#800080",
      red    : "#ff0000",
      silver : "#c0c0c0",
      teal   : "#008080",
      white  : "#ffffff",
      yellow : "#ffff00"
    },
    _hex: function(s){s=parseInt(s).toString(16);return 1<s.length?s:["0",s].join("");},
  // Return color hex value
    color2Hex: function(c)
               {
                 c = c || "";
                 if (!c.indexOf("#"))
                   return c;
                 if (this.colors[c])
                   return this.colors[c];
                 var m = c.match(/\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*/i);
                 if (m)
                   return ["#", this._hex(m[1]), this._hex(m[2]), this._hex(m[3])].join("");
                 return "";
               },
    toPixels: function(num)
              {
                if (num)
                {
                  var m    = num.match(/([0-9]+\.?[0-9]*)\s*(px|pt|em|%)/);
                  var unit = "";
                  if (m)
                  {
                    num  = m[1];
                    unit = m[2];
                  }
                  if (num[0] == ".")
                    num = ["0", num].join("");
                  num = parseFloat(num);
                  if (isNaN(num))
                    num = "";
                  else
                    if (unit)
                    {
                      var base = parseInt($(document.body).css("font-size")) || 16;
                      switch (unit)
                      {
                        case "em": num *= base;       break;
                        case "pt": num *= base / 12;  break;
                        case "%" : num *= base / 100; break;
                      }
                    }
                }
                return num;
              },
    parseURL: function(url)
              {
                var u   = url.match(/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/);
                var ret = {};
                $.each([
                  "source",
                  "protocol",
                  "authority",
                  "userInfo",
                  "user",
                  "password",
                  "host",
                  "port",
                  "relative",
                  "path",
                  "directory",
                  "file",
                  "query",
                  "anchor"
                ], function(i){ret[this]=u[i];});
                if (!ret.host.match(/[a-z0-9]/i))
                  ret.host = "";
                return ret;
              },
  // Create object (map) from array
    makeObject: function(o)
                {
                  var m = {};
                  $.each(o, function(){m[this] = this;});
                  return m;
                },
    trimEventCallback: function(c)
                       {
                         c = c ? c.toString() : "";
                         return $.trim(c.replace(/\r*\n/mg, "").replace(/^function\s*on[a-z]+\s*\(\s*event\s*\)\s*\{(.+)\}$/igm, "$1"));
                       },
  // Encode entities in string
    encode: function(s)
            {
              var e = {'&': '&amp;', '"': '&quot;', '<': '&lt;', '>': '&gt;'};
              return s.toString().replace(/[<>&\"]/g, function(c){return e[c];});
            },
  // Decode entities in string
    decode: function(s){return $("<div />", {html: s || ""}).text();},
  // Compact some style properties and convert colors in hex
    compactStyle: function(s)
                  {
                    if (s.border == "medium none")
                      delete s.border;
                    $.each(s, function(n, v)
                    {
                      if (/color$/i.test(n))
                        s[n] = $.el.utils.color2Hex(v);
                      else
                        if (/^(border|background)$/i.test(n))
                          s[n] = v.replace(/aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|rgb\s*\([^\)]+\)/i, function(m)
                          {
                            return $.el.utils.color2Hex(m);
                          });
                    });
                    if (s["border-width"])
                    {
                      s.border = [s["border-width"], s["border-style"] || "solid", s["border-color"] || "#000"].join(" ");
                      delete s["border-width"];
                      delete s["border-style"];
                      delete s["border-color"];
                    }
                    if (s["background-image"])
                    {
                      s.background = [s["background-color"] || "", s["background-image"], s["background-position"] || "left top", s["background-repeat"] || "repeat"].join(" ");
                      delete s["background-color"];
                      delete s["background-image"];
                      delete s["background-position"];
                      delete s["background-repeat"];
                    }
                    if (s["margin-top"] && s["margin-right"] && s["margin-bottom"] && s["margin-left"])
                    {
                      s.margin = [s["margin-top"], s["margin-right"], s["margin-bottom"], s["margin-left"]].join(" ");
                      delete s["margin-top"];
                      delete s["margin-right"];
                      delete s["margin-bottom"];
                      delete s["margin-left"];
                    }
                    if (s["padding-top"] && s["padding-right"] && s["padding-bottom"] && s["padding-left"])
                    {
                      s.padding = [s["padding-top"], s["padding-right"], s["padding-bottom"], s["padding-left"]].join(" ");
                      delete s["padding-top"];
                      delete s["padding-right"];
                      delete s["padding-bottom"];
                      delete s["padding-left"];
                    }
                    if (s["list-style-type"] || s["list-style-position"] || s["list-style-image"])
                    {
                      s["list-style"] = $.trim([s["list-style-type"] || "", s["list-style-position"] || "", s["list-style-image"] || ""].join(" "));
                      delete s["list-style-type"];
                      delete s["list-style-position"];
                      delete s["list-style-image"];
                    }
                    return s;
                  },
  // Serialize style object into string
    serializeStyle: function(o, c)
                    {
                      var s = [];
                      $.each(c ? this.compactStyle(o) : o, function(n,v){if(v)s.push([n,v].join(":"));});
                      return s.join(";");
                    },
  // Parse class string into object
    parseClass: function(c){c=$.trim(c);return c.length?this.makeObject(c.split(/\s+/)):{};},
  // Serialize class object into string
    serializeClass: function(c){var s=[];$.each(c,function(n){s.push(n);});return s.join(" ");},
  // Return required media type info
    mediaInfo: function(t, c)
               {
                 var l = this.media.length;
                 while (l--)
                   if ((t === this.media[l].type) || (c && (0 <= $.inArray(c, this.media[l].classid))))
                     return this.media[l];
               }
  };

})(jQuery);
